using System;
using System.Collections.Generic;
using System.Text;

namespace DocLibApp
{
    /// <summary>
    /// handles security and user functions
    /// </summary>
    public class doc_security : doc_base
    {
        #region User function
        public static string CreateUser(System.Collections.Hashtable ht)
        {
            //check to see if user exist already
            string user = ht["USERNAME"].ToString();

            if (ExistUserName(user))
                return "User [" + user + "] already exists in the system, please pick a different user name.";

            FormMain.DocLib_QB.TableName = def.tb_user;
            FormMain.DocLib_QB.Get_Insert(ht);
            FormMain.DocLib_QB.RunQuery();

            return "User [" + user + "] successfully created.";
        }

        public static string UpdateUser(string username, System.Collections.Hashtable ht)
        {
            System.Collections.Hashtable ht_where = new System.Collections.Hashtable();
            ht_where["USERNAME"] = username;

            ht["PASSWORD"] = util.MaskString(ht["PASSWORD"].ToString());

            FormMain.DocLib_QB.TableName = def.tb_user;
            FormMain.DocLib_QB.Get_Update(ht, ht_where);
            FormMain.DocLib_QB.RunQuery();

            return "";
        }

        public static System.Collections.ArrayList Get_List_Users()
        {
            FormMain.DocLib_QB.TableName = def.tb_user;
            FormMain.DocLib_QB.Get_Select(new System.Collections.Hashtable());
            return FormMain.DocLib_QB.GetDataRow_ArrayList(true);
        }

        /// <summary>
        /// retrieve user information from user table
        /// </summary>
        /// <param name="username"></param>
        /// <returns></returns>
        public static System.Collections.Hashtable GetUser(string username)
        {
            System.Collections.Hashtable ht = new System.Collections.Hashtable();
            ht["USERNAME"] = username;

            FormMain.DocLib_QB.TableName = def.tb_user;
            FormMain.DocLib_QB.Get_Select(ht);

            System.Collections.Hashtable res = new System.Collections.Hashtable();
            res = FormMain.DocLib_SQLite.GetRowWithDataReaderIntoHash(FormMain.DocLib_QB.SQL);

            return res;
        }

        /// <summary>
        /// if the user name already exists in the system
        /// </summary>
        /// <param name="username"></param>
        /// <returns></returns>
        private static bool ExistUserName(string username)
        {
            System.Collections.Hashtable ht = new System.Collections.Hashtable();
            ht["USERNAME"] = username;

            FormMain.DocLib_QB.TableName = def.tb_user;
            FormMain.DocLib_QB.Get_Select(ht);

            int count = FormMain.DocLib_SQLite.GetRecordCountUseCriteria(FormMain.DocLib_QB.SQL);

            if (count > 0)
                return true;

            return false;
        }

        public static bool AuthenticateUser(System.Collections.Hashtable ht, SQLiteDB adb)
        {
            bool bFlag = false;

            string sql = "select count(*) FROM " + def.tb_user + " WHERE [USERNAME] = '" + ht["USERNAME"].ToString() + "' AND [PASSWORD] = '" + ht["PASSWORD"].ToString() + "'";

            int count = adb.GetRecordCountUseCriteria(sql);

            if (count > 0)
                bFlag = true;

            return bFlag;
        }

        public static void DeleteUser(string username)
        {
            FormMain.DocLib_QB.TableName = def.tb_user;
            FormMain.DocLib_QB.Get_Delete("USERNAME", username);
            FormMain.DocLib_QB.RunQuery();
        }
        #endregion //User Functions

        #region e-signature & audit trail
        /*  general thought:
         * - when sign a document when creating it. Generate the esig hash by using:
         *  - username, date, time, zip file sha1 hash to generate a hash, verify would need all these pieces too
         * 
         * 
         * */
        /// <summary>
        /// Generate a audit trail record, given ht of DOC_ID, DT_EVENT, ACTION, SIGN_USER
        /// tested.
        /// </summary>
        /// <param name="ht"></param>
        /// <returns></returns>
        public static bool CreateAuditTrail(System.Collections.Hashtable ht)
        {
            //DOC_ID, EVENT_ID, DT_EVENT, ACTION, HASH, SIGN_USER
           
            //create the hash from the info
            string pattern = util.PutHashInPattern(ht, def.Pattern_AuditTrailHash);

            string Hash = util.EncryptString(pattern, def.key_audit_trail);

            ht["HASH"] = Hash;

            FormMain.DocLib_QB.TableName = def.tb_doc_audit;
            FormMain.DocLib_QB.Get_Insert(ht);
            FormMain.DocLib_QB.RunQuery();

            return true;
        }

        /// <summary>
        /// delete audit trail for a document
        /// </summary>
        /// <param name="doc_id"></param>
        public static void DeleteAuditTrail(string doc_id)
        {
            FormMain.DocLib_QB.TableName = def.tb_doc_audit;
            FormMain.DocLib_QB.Get_Delete("DOC_ID", doc_id);
            FormMain.DocLib_QB.RunQuery();
        }

        /// <summary>
        /// Verify audit trail is valid by matching hash stored in database against the audit event data pattern
        /// tested.
        /// </summary>
        /// <param name="doc_id"></param>
        /// <returns></returns>
        public static bool VerifyAuditTrail(string doc_id)
        {
            System.Collections.Hashtable ht = new System.Collections.Hashtable();
            ht["DOC_ID"] = doc_id;

            FormMain.DocLib_QB.TableName = def.tb_doc_audit;
            FormMain.DocLib_QB.Get_Select(ht);

            System.Collections.Hashtable htResult = FormMain.DocLib_SQLite.GetRowWithDataReaderIntoHash(FormMain.DocLib_QB.SQL);

            string Hash_in_data = htResult["HASH"].ToString().Trim();

            htResult.Remove("HASH");

            string pattern = util.PutHashInPattern(htResult, def.Pattern_AuditTrailHash);
            string pattern_from_hash = util.DecryptString(Hash_in_data, def.key_audit_trail);

            if (pattern == pattern_from_hash)
                return true;

            return false;
        }
        #endregion //e-signature & audit trail

        #region Security Role
        /// <summary>
        /// retrieve security role header information
        /// </summary>
        /// <param name="role"></param>
        /// <returns></returns>
        public static System.Collections.Hashtable Get_Role_Header(string role)
        {
            FormMain.DocLib_QB.TableName = def.tb_sec_role_header;
            FormMain.DocLib_QB.Get_Select("ROLE_ID", role);
            return FormMain.DocLib_QB.GetDataOneRowInHash();
        }

        public static List<string> GetRoleList()
        {
            List<string> RoleList = new List<string>();

            List<string> FieldList = new List<string>();
            FieldList.Add("ROLE_ID");

            FormMain.DocLib_QB.TableName = def.tb_sec_role_header;
            FormMain.DocLib_QB.Get_Select(FieldList, new System.Collections.Hashtable());
            return FormMain.DocLib_QB.GetData_OneColumn();
        }

        /// <summary>
        /// get a list of security roles
        /// </summary>
        /// <returns></returns>
        public static System.Collections.ArrayList GetListOfRoles()
        {
            System.Collections.ArrayList alist = new System.Collections.ArrayList();

            System.Collections.Hashtable ht = new System.Collections.Hashtable();

            FormMain.DocLib_QB.TableName = def.tb_sec_role_header;
            FormMain.DocLib_QB.Get_Select(ht);
            alist = FormMain.DocLib_QB.GetDataRow_ArrayList(true);

            return alist;
        }

        /// <summary>
        /// check to see if a user can execute certain procedure
        /// </summary>
        /// <param name="user"></param>
        /// <param name="procedure"></param>
        /// <returns></returns>
        public bool Can_User_Execute_Procedure(string user, string procedure)
        {
            List<string> ProcList = Get_User_Role_Procedure(user);

            if (ProcList.Contains(procedure))
                return true;

            return false;
        }

        /// <summary>
        /// assign a user to a role, only 1 role per user
        /// a user could not be assign to multiple roles
        /// </summary>
        /// <param name="role"></param>
        /// <param name="user"></param>
        /// <returns></returns>
        public static string Role_Assign(string role, string user)
        {
            FormMain.DocLib_QB.TableName = def.tb_sec_role_assignment;

            //if the role assignment exist for the user
            if (!string.IsNullOrEmpty(Get_User_Role(user)))
            {
                System.Collections.Hashtable htDelete = new System.Collections.Hashtable();
                htDelete["USER"] = user;
                FormMain.DocLib_QB.Get_Delete(htDelete);
                FormMain.DocLib_QB.RunQuery();
            }

            System.Collections.Hashtable htInsert = new System.Collections.Hashtable();
            htInsert["ROLE_ID"] = role;
            htInsert["USER"] = user;
            FormMain.DocLib_QB.Get_Insert(htInsert);
            FormMain.DocLib_QB.RunQuery();

            return "";
        }

        public static string Get_User_Role(string user)
        {
            FormMain.DocLib_QB.TableName = def.tb_user;
            System.Collections.Hashtable ht = new System.Collections.Hashtable();
            ht["USERNAME"] = user;
            List<string> FieldList = new List<string>();
            FieldList.Add("ROLE_ID");
            FormMain.DocLib_QB.Get_Select(FieldList, ht);
            return FormMain.DocLib_QB.GetDataString();
        }

        /// <summary>
        /// get a list of procedure associate w/ the user's role
        /// </summary>
        /// <param name="user"></param>
        /// <returns></returns>
        public static List<string> Get_User_Role_Procedure(string user)
        {
            List<string> ProcedureList = new List<string>();
            string role_id = Get_User_Role(user);

            ProcedureList = Get_Procedure_For_Role(role_id);

            return ProcedureList;
        }

        public static List<string> Get_Procedure_For_Role(string role)
        {
            List<string> ProcList = new List<string>();

            FormMain.DocLib_QB.TableName = def.tb_sec_role_entry;
            List<string> FieldList = new List<string>();
            FieldList.Add("PROCEDURE");
            System.Collections.Hashtable ht = new System.Collections.Hashtable();
            ht["ROLE_ID"] = role;

            FormMain.DocLib_QB.Get_Select(FieldList, ht);
            ProcList = FormMain.DocLib_QB.GetData_OneColumn();

            return ProcList;
        }

        /// <summary>
        /// Creating new roles if role does not exist,
        /// if exist, update the role with new Procedure List and also update Description
        /// </summary>
        /// <param name="role"></param>
        /// <param name="ProcedureList"></param>
        public static string Role_Save(string role, string Description, List<string> ProcedureList)
        {
            string res = "";

            if (!If_Role_Exist(role))
            {
                //header
                FormMain.DocLib_QB.TableName = def.tb_sec_role_header;
                System.Collections.Hashtable htInsert = new System.Collections.Hashtable();
                htInsert["ROLE_ID"] = role;
                htInsert["DESCRIPTION"] =Description;
                htInsert["DT_CREATE"] = SQLiteDB.DateTimeToString(System.DateTime.Now);
                htInsert["DT_UPDATE"] = SQLiteDB.DateTimeToString(System.DateTime.Now);
                FormMain.DocLib_QB.Get_Insert(htInsert);
                FormMain.DocLib_QB.RunQuery();

                //Role Entry
                FormMain.DocLib_QB.TableName = def.tb_sec_role_entry;
                System.Collections.Hashtable htRoleEntry = new System.Collections.Hashtable();
                htRoleEntry["ROLE_ID"] = role;
                foreach (string proc in ProcedureList)
                {
                    htRoleEntry["PROCEDURE"] = proc;
                    FormMain.DocLib_QB.Get_Insert(htRoleEntry);
                    FormMain.DocLib_QB.RunQuery();
                }

                res = "New role [" + role + "] created successfully.";
            }
            else
            {
                //header
                FormMain.DocLib_QB.TableName = def.tb_sec_role_header;
                System.Collections.Hashtable htUpdate = new System.Collections.Hashtable();
                htUpdate["DESCRIPTION"] = Description;
                htUpdate["DT_UPDATE"] = SQLiteDB.DateTimeToString(System.DateTime.Now);
                System.Collections.Hashtable htWhere = new System.Collections.Hashtable();
                htWhere["ROLE_ID"] = role;
                FormMain.DocLib_QB.Get_Update(htUpdate, htWhere);
                FormMain.DocLib_QB.RunQuery();
                
                //Role Entry
                FormMain.DocLib_QB.TableName = def.tb_sec_role_entry;
                //erase all previous entries
                FormMain.DocLib_QB.Get_Delete("ROLE_ID", role);
                FormMain.DocLib_QB.RunQuery();
                //insert all new list
                foreach (string proc in ProcedureList)
                {
                    System.Collections.Hashtable htInsert = new System.Collections.Hashtable();
                    htInsert["ROLE_ID"] = role;
                    htInsert["PROCEDURE"] = proc;
                    FormMain.DocLib_QB.Get_Insert(htInsert);
                    FormMain.DocLib_QB.RunQuery();
                }

                res = "Role [" + role + "] updated successfully.";
            }

            return res;
        }

        public static bool If_Role_Exist(string role)
        {
            System.Collections.Hashtable ht = new System.Collections.Hashtable();
            ht["ROLE_ID"] = role;
            FormMain.DocLib_QB.TableName = def.tb_sec_role_header;
            FormMain.DocLib_QB.Get_Select(ht);
            return FormMain.DocLib_QB.IfRecordExist();
        }
        #endregion
    }
}
